package sale.wxb.loveshopping.utils;

import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 树结构帮助类 基于 Hutool TreeUtils
 */
@Slf4j
public class TreeStructureUtil {

    /**
     * 将集合转成树结构
     * 要求 需要转换的集合实体中包含 id, parentId, name 字段
     * 要求 目标集合类型包含 children字段 children 必须是List<T> 类型
     * @param list 要转换的集合
     * @param elementType 目标类型
     * @return List<T>
     */
    public static <T, R> List<R> getTree(List<T> list, Class<R> elementType) {
        List<Tree<String>> treeList = TreeUtil.build(list, "0", (node, tree) -> {
            List<Field> fields = new ArrayList<>();
            Class<?> classObject = node.getClass();

            // 递归方式读取全部字段
            while (classObject != null) {
                fields.addAll(Arrays.asList(classObject.getDeclaredFields()));
                classObject = classObject.getSuperclass();
            }

            // 设置字段
            fields.forEach(field -> {
                // 设置为可访问
                field.setAccessible(true);
                try {
                    String name = field.getName();
                    Object value = field.get(node);
                    if (name.equals("id")) {
                        tree.setId(value.toString());
                    } else if (name.equals("name")) {
                        tree.setName((String) value);
                    } else if (name.equals("parentId")) {
                        tree.setParentId( value == null ? "0" : value.toString());
                    } else if (!name.equals("serialVersionUID")) {
                        tree.put(field.getName(), field.get(node));
                    }
                } catch (IllegalAccessException e) {
                    log.error("Tree: 设置字段失败:" + e.getMessage());
                }
            });
        });
        return JSONUtil.toList(JSONUtil.parseArray(treeList), elementType);
    }
}
